﻿using AutoMapper;
using MediatR;
using S.Archives.Domain.S.ArchivesModel;
using S.Archives.Infrstructre.Imp;
using S.Archives.Infrstructre.InterFace;
using S.Archives.Read.Api.Application.Command;
using S.Archives.Read.Api.Dto;
using System.Collections.Generic;

namespace S.Archives.Read.Api.Application.CommandHandlers
{
    public class SheepFileCommandHandler : IRequestHandler<PLBatchBreedingCommand, List<string>>, IRequestHandler<IsOkMatingSpeciesCommand, bool>, IRequestHandler<GetSheepGenealogyCommand, SheepGenealogy>, IRequestHandler<GetSheepGenealogyShowListCommand, SheepGenealogyShow>
    {
        private readonly ISheepFileRepository sheepFileRepository;
        private readonly IMapper mapper;

        public SheepFileCommandHandler(ISheepFileRepository sheepFileRepository, IMapper mapper)
        {
            this.sheepFileRepository = sheepFileRepository;
            this.mapper = mapper;
        }

        /// <summary>
        /// 批量配种筛选方法
        /// </summary>
        /// <param name="maternalEITags">种母耳标string列表</param>
        /// <param name="paternalEITag">种公耳标</param>
        /// <returns>不合格的种母耳标string列表</returns>
        public List<string> AllGenealogicalRecordsScreening(List<string> maternalEITags, string paternalEITag)
        {
            List<string> NonBreedingList = new List<string>();
            foreach (var item in maternalEITags)
            {
                var sheopfilelist = sheepFileRepository.GetAll();
                var paternalScreening = GetSheepGenealogy(paternalEITag, sheopfilelist);
                var maternalScreening = GetSheepGenealogy(item, sheopfilelist);
                var paternallist = FlattenTree(paternalScreening);
                var maternallist = FlattenTree(maternalScreening);
                var ScreeningList = GetDuplicates(paternallist, maternallist);

                bool sel = ScreeningList.Count() <= 0;
                if (!sel)
                {
                    NonBreedingList.Add(item);
                }
            }
            return NonBreedingList;
        }

        /// <summary>
        /// 判断是否可配种
        /// </summary>
        /// <param name="paternalEITag">种公</param>
        /// <param name="maternalEITag">种母</param>
        /// <returns>是否可配</returns>
        public bool GenealogicalRecordsScreening(string paternalEITag, string maternalEITag)
        {
            var sheopfilelist = sheepFileRepository.GetAll();
            var paternalScreening = GetSheepGenealogy(paternalEITag, sheopfilelist);
            var maternalScreening = GetSheepGenealogy(maternalEITag, sheopfilelist);
            var paternallist = FlattenTree(paternalScreening);
            var maternallist = FlattenTree(maternalScreening);
            var ScreeningList = GetDuplicates(paternallist, maternallist);
            return ScreeningList.Count() <= 0;
        }

        // GetSheepGenealogy(耳号,多少层, sheepFileRepository.getall())
        /// <summary>
        ///递归二叉树
        /// </summary>
        /// <param name="eiTag">耳号</param>
        /// <param name="severalgenerations">多少层默认4层</param>
        /// <param name="DataSource">sheepFileRepository.getall()</param>
        /// <param name="AlgebraSeveralGenerations"></param>
        /// <returns></returns>
        public SheepGenealogy GetSheepGenealogy(string eiTag, IQueryable<SheepFileModel> DataSource, int severalgenerations = 4, int AlgebraSeveralGenerations = 1)
        {
            SheepFileModel sfmodel = DataSource.Where(a => a.EarTag == eiTag).FirstOrDefault();
            if (sfmodel == null)
            {
                return null;
            }

            if (AlgebraSeveralGenerations >= severalgenerations)
            {
                return null;
            }

            SheepGenealogy sgdto = new SheepGenealogy();
            AlgebraSeveralGenerations++;
            sgdto.Father = GetSheepGenealogy(sfmodel.ParentEarTag, DataSource, severalgenerations, AlgebraSeveralGenerations);
            sgdto.Monther = GetSheepGenealogy(sfmodel.MotherEarTag, DataSource, severalgenerations, AlgebraSeveralGenerations);
            sgdto.SheepEarTag = eiTag;
            sgdto.Key = sfmodel.SheepFileId;
            return sgdto;
        }

        /// <summary>
        /// 二叉遍历
        /// </summary>
        /// <param name="sheep"></param>
        /// <returns></returns>
        public List<SheepGenealogy> FlattenTree(SheepGenealogy sheep)
        {
            List<SheepGenealogy> result = new List<SheepGenealogy>();
            // 添加当前节点到结果列表
            result.Add(sheep);
            // 递归遍历左子树
            if (sheep.Father != null)
            {
                result.AddRange(FlattenTree(sheep.Father));
            }
            // 递归遍历右子树
            if (sheep.Monther != null)
            {
                result.AddRange(FlattenTree(sheep.Monther));
            }
            return result;
        }

        /// <summary>
        /// 哈希对比
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list1"></param>
        /// <param name="list2"></param>
        /// <returns></returns>
        public List<T> GetDuplicates<T>(List<T> list1, List<T> list2)
        {
            var duplicates = list1.Where(item1 => list2.Any(item2 => item2.Equals(item1))).ToList();
            return duplicates;
        }


        /// <summary>
        /// 批量配种筛选
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<List<string>> Handle(PLBatchBreedingCommand request, CancellationToken cancellationToken)
        {
            return AllGenealogicalRecordsScreening(request.maternalEITags, request.paternalEITag);
        }

        /// <summary>
        /// 判断是否可以配种
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<bool> Handle(IsOkMatingSpeciesCommand request, CancellationToken cancellationToken)
        {
            return GenealogicalRecordsScreening(request.paternalEITag, request.maternalEITag);
        }

        /// <summary>
        /// 获取羊只系谱
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<SheepGenealogy> Handle(GetSheepGenealogyCommand request, CancellationToken cancellationToken)
        {
            var DataSource = sheepFileRepository.GetAll();
            return GetSheepGenealogy(request.eiTag, DataSource, 4, 1);
             
        }

        // GetSheepGenealogy(耳号,多少层, sheepFileRepository.getall())
        /// <summary>
        ///递归显示系谱方法(name,childrem类型)
        /// </summary>
        /// <param name="eiTag">根节点耳号</param>
        /// <param name="severalgenerations">
        /// </param>
        /// <param name="DataSource">sheepFileRepository.getall()</param>
        /// <param name="AlgebraSeveralGenerations"></param>
        /// <returns></returns>
        public SheepGenealogyShow SheepGenealogyShowList(string eiTag, IQueryable<SheepFileModel> DataSource, int severalgenerations = 4, int AlgebraSeveralGenerations = 1)
        {
            SheepFileModel sfmodel = DataSource.Where(a => a.EarTag == eiTag).FirstOrDefault();
            if (sfmodel == null)
            {
                return null;
            }

            if (AlgebraSeveralGenerations >= severalgenerations)
            {
                return null;
            }
            SheepGenealogyShow sg = new SheepGenealogyShow();
            List<SheepGenealogyShow> sglsdto = new List<SheepGenealogyShow>();
            AlgebraSeveralGenerations++;
            sg.name = sfmodel.EarTag;
            sg.Sex = sfmodel.Sex == 1 ? true : false;
            var Father = SheepGenealogyShowList(sfmodel.ParentEarTag, DataSource, severalgenerations, AlgebraSeveralGenerations);
            var Monther = SheepGenealogyShowList(sfmodel.MotherEarTag, DataSource, severalgenerations, AlgebraSeveralGenerations);
            if (Father != null)
            {
                sglsdto.Add(Father);
                sglsdto.Add(Monther);
            }
            sg.children = sglsdto;
            return sg;
        }
        /// <summary>
        /// 递归显示羊只系谱
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<SheepGenealogyShow> Handle(GetSheepGenealogyShowListCommand request, CancellationToken cancellationToken)
        {
            var DataSource = sheepFileRepository.GetAll();
            return  SheepGenealogyShowList(request.eiTag, DataSource, 5, 1);
        }
    }
}